#!/usr/bin/python
# vi: et sw=2
#

import pygtk
import gtk

from AppletModel import *

# This is the list of sinks
class AppletView(gtk.Window):
  # FIXME define signals

  def __init__(self, settings, model = None):
    gtk.Window.__init__(self, gtk.WINDOW_POPUP);

    self.model = model or AppletModel()
    self.box = None
    self.view_frame = gtk.Frame()
    self.settings = settings
    self.volume_icon = gtk.Image()
    self.volume_label = gtk.Label()
    self.status_icon = gtk.Image()
    self.icon_size = None

    self.view_frame.set_shadow_type(gtk.SHADOW_OUT)

    self.add(self.view_frame)

    self.model.connect("data-changed", self.update_view)

    # This make window grow and shrink
    self.set_property("resizable", False)

    print "AppletView is now initialized with model:", self.model
    pass

    #
    # __init__ end
    #

  def update_settings(self, settings):
    self.settings = settings
    self.update_view()  

    #
    # update_settings end
    #

  def update_volume_icon(self):
    if self.model.sink_count() == 0:
      return

    # FIXME get from GConf
    index = 0

    if index >= self.model.sink_count():
      index = 0

    #vol = int(self.model.sink_get_avg_volume())
    vol = int(self.model.sink_get_volume(index))
    mute = self.model.sink_get_mute(index)

    icon_name = None

    if vol == 0 or mute:
      icon_name = "audio-volume-muted"
    elif vol < 34:
      icon_name = "audio-volume-low"
    elif vol < 67:
      icon_name = "audio-volume-medium"
    else:
      icon_name = "audio-volume-high"

    icon_theme = gtk.icon_theme_get_default()

    if not icon_theme.has_icon(icon_name):
      print "Icon (" + icon_name + ") cannot found from default theme"

    self.volume_icon.set_from_pixbuf(
        icon_theme.load_icon(icon_name, self.icon_size,
                             gtk.ICON_LOOKUP_USE_BUILTIN)
    )

    self.volume_icon.set_tooltip_text("Volume: " + str(vol) + "%")
    self.volume_label.set_label(str(vol) + "%")

    #
    # update_volume_icon end
    #

  def update_view(self, model = None):

    # Update volume_icon
    self.update_volume_icon()

    # layout changed -> need rebuilding
    if not isinstance(self.box, self.settings["box_function"]):
      self._build_new_view()
      return

    # Lazy fix
    if len(self.box.get_children()) != \
       self.model.sink_count() + 1 + self.model.sink_input_count():
      self._build_new_view()
      return

    # Check every child and mark them old
    for child in self.box.get_children():

      if isinstance(child, gtk.VSeparator) or \
         isinstance(child, gtk.HSeparator):
        pass
      else:
        index = child.sink_index
        type = child.sink_type

        get_name = self.model.sink_get_name
        get_desc = self.model.sink_get_desc
        get_volume_dB = self.model.sink_get_volume_dB
        get_volume = self.model.sink_get_volume
        get_mute = self.model.sink_get_mute

        if type == "sink_input":
          get_name = self.model.sink_input_get_name
          get_desc = self.model.sink_input_get_desc
          get_volume_dB = self.model.sink_input_get_volume_dB
          get_volume = self.model.sink_input_get_volume
          get_mute = self.model.sink_input_get_mute

        #child.set_tooltip_text(get_name(index) + ": " +
        #                       get_desc(index) + "\n" +
        #                       str(get_volume_dB(index)) + " dB")
        self._update_sink_widget(
          child,
          get_name(index),
          get_desc(index),
          get_volume(index),
          str(get_volume_dB(index)) + " dB"
        )

        child.volume_adjust.set_value(get_volume(index))

        #child.mute.set_label(str(get_volume_dB(index)) + " dB")
        self._update_mute_widget(
          child.mute,
          get_mute(index),
          get_volume(index),
          str(get_volume_dB(index)) + "dB"
        )

    pass

    #
    # update_view end
    #

  def _build_new_view(self):
    box = self.settings["box_function"]()

    for i in range(self.model.sink_count()):
      box.add(self.build_sink_from_builder(i))

    # FIXME check configs
    box.add(gtk.VSeparator())

    for i in range(self.model.sink_input_count()):
      box.add(self.build_sink_input_from_builder(i))

    if self.box != None:
      self.view_frame.remove(self.box)

    self.box = box
    self.view_frame.add(self.box)

    if self.get_property("visible") == True:
      self.show_all()
    else:
      self.box.show_all()

    pass

    #
    # _build_new_view end
    #

  def build_sink_from_builder(self, index):
    wTree = self.settings["layout_function"]()

    return self.build_widget(wTree,
                             index,
                             "sink",
                             self.model.sink_get_volume,
                             self.model.sink_get_volume_dB,
                             self.model.sink_get_name,
                             self.model.sink_get_desc,
                             self.model.sink_get_mute)

    #
    # build_sink_from_builder end
    #

  def build_sink_input_from_builder(self, index):
    wTree = self.settings["layout_function"]()

    return self.build_widget(wTree,
                             index,
                             "sink_input",
                             self.model.sink_input_get_volume,
                             self.model.sink_input_get_volume_dB,
                             self.model.sink_input_get_name,
                             self.model.sink_input_get_desc,
                             self.model.sink_input_get_mute)

    #
    # build_sink_input_from_builder end
    #

  def build_widget(self, wTree, index, sink_type, get_volume,
                         get_volume_dB,
                         get_name, get_desc, get_mute):
    sink = wTree.get_object("sink")

    if sink == None:
      return gtk.Label("Check builderfile")

    sink.sink_index = index
    sink.sink_type = sink_type
    sink.scroll = wTree.get_object("volume_scroll")

    # FIXME Create function to do this so update_view could also use it
    self._update_sink_widget(
        sink,
        get_name(index),
        get_desc(index),
        get_volume(index),
        str(get_volume_dB(index)) + " dB"
    )
    #sink.set_tooltip_text(get_name(index) + ": " + get_desc(index) + "\n" +
    #                      str(get_volume_dB(index)) + " dB")

    volume_adjust = wTree.get_object("volume_adjust")
    mute = wTree.get_object("mute")

    if mute != None and isinstance(mute, gtk.Button):
      #if get_mute(index):
      #  mute.set_label("-inf dB");
      #else:
      #mute.set_label(str(get_volume_dB(index)) + " dB")
      self._update_mute_widget(
        mute,
        get_mute(index),
        get_volume(index),
        str(get_volume_dB(index)) + "dB"
      )

      mute.connect("button-press-event", self.on_mute_button_press_event, sink)
      sink.mute = mute

    if volume_adjust != None:
      volume_adjust.set_value(get_volume(index))
      volume_adjust.connect("value-changed", self.volume_changed_event, sink)
      sink.volume_adjust = volume_adjust

      # NOTE some reason doesn't work older pygtk ???
      #sink.scroll.set_increments(volume_adjust.get_step_increment(),
      #                           volume_adjust.get_page_increment())

    return sink

    #
    # build_widget end
    #

  def _update_sink_widget(self, sink, name, desc, volume, volume_db):
    sink.set_tooltip_text(name + ": " + desc + "\n" + volume_db)

    pass

    #
    # _update_sink_widget
    #

  def _update_mute_widget(self, widget, mute, volume, volume_db):

    icon_name = None

    if volume == 0 or mute:
      icon_name = "audio-volume-muted"
    elif volume < 34:
      icon_name = "audio-volume-low"
    elif volume < 67:
      icon_name = "audio-volume-medium"
    else:
      icon_name = "audio-volume-high"

    icon_theme = gtk.icon_theme_get_default()

    if not icon_theme.has_icon(icon_name):
      print "Icon (" + icon_name + ") cannot found from default theme"

    image = gtk.Image()
    image.set_from_pixbuf(
        icon_theme.load_icon(icon_name, 24,
                             gtk.ICON_LOOKUP_USE_BUILTIN)
    )
    widget.set_image(image)
    widget.set_tooltip_text(volume_db)

    #
    # _update_mute_widget
    #

  # Events
  #

  def volume_changed_event(self, adjust, sink_widget):
    volume = int(adjust.get_value())
    type   = sink_widget.sink_type
    index  = sink_widget.sink_index

    if type == "sink":
      self.model.sink_set_volume(index, volume)
    elif type == "sink_input":
      self.model.sink_input_set_volume(index, volume)

    pass

    #
    # volume_changed_event end
    #

  def on_mute_button_press_event(self, button, event, sink_widget):
    type  = sink_widget.sink_type
    index = sink_widget.sink_index

    mute  = None

    if type == "sink":
      mute = self.model.sink_get_mute(index)
      self.model.sink_set_mute(index, not mute)
    elif type == "sink_input":
      mute = self.model.sink_input_get_mute(index)
      self.model.sink_input_set_mute(index, not mute)

  pass
